define(
	[
		'require',
		'broada/wijmo/wijcalendar/jquery.wijmo.wijcalendar'
	],
	function(require) {
		"use strict";

		var canlendarPrototype = wijmo.calendar.wijcalendar.prototype;
		var htmlTextWriter = wijmo.calendar.htmlTextWriter;
		var wijMyGrid = wijmo.calendar.wijMyGrid;

		canlendarPrototype._getCalendarHtml = function() {
			this._createMonthViews();
			var hw = new htmlTextWriter();
			if (this.options.selectionMode.month) {
				hw.write(this._getMonthsHtml());
			} else {
				hw.write(this._getMonthGroupHtml());
			}
			return hw.toString();
		};
		canlendarPrototype._getMonthsHtml = function() {
			var date = this.getDisplayDate(),
				mv, width, hw, wijCSS = this.options.wijCSS,
				r, c;
			if (this._isSingleMonth()) {
				this._myGrid = new wijMyGrid(this);
				return this._myGrid.getHtml();
			}
		};
		canlendarPrototype._onMyGridClicked = function(e) {
			if (this._myGrid === undefined) {
				return false;
			}
			if (this._isAnimating()) {
				return false;
			}
			var cell = $(e.currentTarget),
				index = parseInt(cell.attr('index'), 10),
				value = parseInt(cell.attr('value'), 10),
				wijCSS = this.options.wijCSS,
				curTable = this.element.find('.' + wijCSS.datepickerCalendar),
				wrapper, container, w, h, bounds, $content, date, mv, nextTable, calendar = this;

			//if (!cell.hasClass(wijCSS.stateActive)) {
				this._myGrid.select(index, value);
				curTable.find("td." + wijCSS.stateActive).removeClass(wijCSS.stateActive).removeClass(wijCSS.stateHighlight);
				cell.addClass(wijCSS.stateActive);

				if (this.options.selectionMode.month && this._myGrid.gridType == "month") {
					date = this.getDisplayDate();
					this._trigger('selectedMonthChanged', null, {
						date: date
					});
				}
			//}

			if (this.options.selectionMode.month && this._myGrid.gridType == "month") {
				return false;
			}

			if (this._myGrid.gridType === "decade") {
				this._myGrid.gridType = "year";
			} else {
				if (this._myGrid.gridType === "year") {
					this._myGrid.gridType = "month";
				} else {
					this._myGrid = undefined;
				}
			}
			this._refreshTitle();
			w = curTable.outerWidth();
			h = Math.max(curTable.outerHeight(), 154);
			if (curTable.parent().is('.wijmo-wijcalendar-aniwrapper')) {
				container = curTable.parent();
			} else {
				container = $.createWrapper(curTable).css({
					overflow: 'hidden'
				}).removeClass(wijCSS.effectsWrapper).addClass('wijmo-wijcalendar-aniwrapper').width(w).height(h);
			}
			bounds = $.extend({}, cell.position(), {
				width: cell.width(),
				height: cell.height()
			});
			if (this._myGrid === undefined) {
				this._createMonthViews();
				date = this.getDisplayDate();
				mv = this._getMonthView(date);
				$content = this._customize(mv.getHtml(true));
			} else {
				$content = $(this._myGrid.getHtml(true));
			}
			nextTable = $content.height(h).appendTo(container);
			wrapper = $.createWrapper(nextTable).css({
				overflow: 'hidden'
			}).removeClass(wijCSS.effectsWrapper).addClass('wijmo-wijcalendar-aniwrapper').css($.extend(bounds, {
				border: 'solid 1px #cccccc',
				position: 'absolute'
			}));
			this.element.data('animating.wijcalendar', true);
			wrapper.animate({
				left: 0,
				top: 0,
				width: w,
				height: h
			}, this.options.duration || 500, null, function() {
				nextTable.css("width", "");
			});
			curTable.animate({
				opacity: 0
			}, this.options.duration || 500, null, function() {
				curTable.remove();
				while (nextTable.parent().is('.wijmo-wijcalendar-aniwrapper')) {
					nextTable.parent().replaceWith(nextTable);
				}
				if (calendar._myGrid === undefined) {
					calendar.element.width('').height('');
				}
				calendar._bindEvents();
				calendar.element.data('animating.wijcalendar', false);
			});
			return false;
		};

		var old_bindEvents = canlendarPrototype._bindEvents;
		canlendarPrototype._bindEvents = function() {
			old_bindEvents.call(this);
			this.element.find(".ui-datepicker-unselectable").unbind().bind({
				"click.wijcalendar": function(e) {
					e.preventDefault();
				}
			});
		};

		wijMyGrid.prototype.getHtml = function(date, tableOnly) {
			if (date === undefined) {
				date = this.calendar.getDisplayDate();
			} else {
				if (typeof(date) === 'boolean') {
					tableOnly = date;
					date = this.calendar.getDisplayDate();
				}
			}
			tableOnly = !!tableOnly;
			var o = this.calendar.options,
				rows = 3,
				cols = 4,
				hw = new htmlTextWriter(),
				wijCSS = o.wijCSS,
				height, year, startMonth, startYear, startDecade, ms, i, j, index, selected, outofRange, cellText, v, cls;
			if (o.showTitle && !tableOnly) {
				hw.write(this.calendar._getHeaderHtml(null, true, true));
			}
			height = 100 / rows + '%';
			height = '30%';
			hw.writeBeginTag('table');
			hw.writeAttribute('class', wijCSS.datepickerCalendar + ' wijmo-wijcalendar-mygrid');
			hw.writeAttribute('role', 'grid');
			hw.writeAttribute('onselectstart', 'return false;');
			hw.writeTagRightChar();
			year = date.getFullYear();
			startMonth = date.getFullYear() * 12;
			startYear = Math.floor(year / 10) * 10 - 1;
			startDecade = Math.floor(year / 100) * 100 - 10;
			ms = this.culture.calendar.months;
			for (i = 0; i < rows; i++) {
				hw.writeBeginTag('tr');
				hw.writeAttribute('height', height);
				hw.writeTagRightChar();
				for (j = 0; j < cols; j++) {
					index = i * 4 + j;
					selected = false;
					outofRange = false;
					cellText = '';
					v = null;
					switch (this.gridType) {
						case "month":
							if (date.getMonth() === index) {
								selected = true;
							}
							v = index;
							cellText = ms.namesAbbr[index];
							outofRange = ((startMonth + index) < (o.minDate.getFullYear() * 12 + o.minDate.getMonth())) || ((startMonth + index) > (o.maxDate.getFullYear() * 12 + o.maxDate.getMonth()));
							break;
						case "year":
							// if(index === 0 || index === 11) {
							// 	outofRange = true;
							// }
							v = startYear + index;
							if (v < o.minDate.getFullYear() || v > o.maxDate.getFullYear()) {
								outofRange = true;
							} else {
								selected = (year === v);
							}
							cellText = v.toString();
							break;
						case "decade":
							// if(index === 0 || index === 11) {
							// 	outofRange = true;
							// }
							v = startDecade + index * 10;
							if (v + 10 < o.minDate.getFullYear() || v > o.maxDate.getFullYear()) {
								outofRange = true;
							} else {
								selected = (year >= v && year < (v + 10));
							}
							cellText = v.toString() + '-<br/>' + (v + 9).toString();
							break;
					}
					cls = wijCSS.datepickerWeekDay;
					if (outofRange) {
						cls = cls + ' ' + wijCSS.datepickerOtherMonth + ' ' + wijCSS.prioritySecondary + ' ' + wijCSS.datepickerUnselectable;
					} else {
						if (!o.disabledState && !o.disabled) {
							cls += " wijmo-wijcalendar-day-selectable";
						}
					}
					cls += " " + wijCSS.stateDefault + (outofRange ? ' ' + wijCSS.stateDisabled : '') + (selected ? ' ' + wijCSS.stateActive + ' ' + wijCSS.stateHighlight : '');
					hw.writeBeginTag('td');
					hw.writeAttribute('class', cls);
					hw.writeAttribute('role', 'gridcell');
					//hw.writeAttribute('width', width);
					hw.writeAttribute('index', index.toString());
					hw.writeAttribute('value', v.toString());
					hw.writeAttribute('other', outofRange.toString());
					hw.writeTagRightChar();
					hw.writeBeginTag('a');
					hw.writeAttribute('href', '#');
					hw.writeTagRightChar();
					hw.write(cellText);
					hw.writeEndTag('a');
					hw.writeEndTag('td');
				}
				hw.writeEndTag('tr');
			}
			hw.writeEndTag('table');
			return hw.toString();
		};

		$.wijmo.registerWidget("wijcalendar", canlendarPrototype);

		var MonthSelector = Ember.Component.extend({
			didInsertElement: function() {
				var view = this;
				this.$().wijcalendar({
					displayDate: new Date(+view.get("date")),
					selectionMode: {
						month: true
					},
					selectedMonthChanged: function(e, args) {
						view.set("date", new Date(+args.date));
					}
				});
			},

			dateChange: Ember.observer('date', function() {
				var date = this.get("date");
				if (+date != +this.$().wijcalendar('getDisplayDate')) {
					this.$().wijcalendar({
						displayDate: new Date(+date)
					});
				}
			})
		});

		return MonthSelector;
	}
);